#!/usr/bin/env python3
"""
杂志图片管理桌面APP
基于tkinter的原生桌面应用
"""

import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import os
import shutil
from PIL import Image, ImageTk
import json
from datetime import datetime
import threading
import webbrowser

class MagazineApp:
    def __init__(self, root):
        self.root = root
        self.root.title("📖 杂志图片管理器")
        self.root.geometry("1200x800")
        self.root.minsize(1000, 600)
        
        # 设置应用图标
        try:
            self.root.iconbitmap("")
        except:
            pass
            
        # 初始化数据
        self.upload_dir = "static/uploads"
        self.images_data = {}
        self.current_image = None
        
        # 确保上传目录存在
        os.makedirs(self.upload_dir, exist_ok=True)
        
        self.setup_ui()
        self.load_images()
        
    def setup_ui(self):
        """设置用户界面"""
        # 主框架
        main_frame = ttk.Frame(self.root)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)
        
        # 顶部工具栏
        toolbar = ttk.Frame(main_frame)
        toolbar.pack(fill=tk.X, pady=(0, 10))
        
        # 上传按钮
        upload_btn = ttk.Button(toolbar, text="📤 上传图片", command=self.upload_images)
        upload_btn.pack(side=tk.LEFT, padx=(0, 10))
        
        # 批量删除按钮
        delete_btn = ttk.Button(toolbar, text="🗑️ 删除选中", command=self.delete_selected)
        delete_btn.pack(side=tk.LEFT, padx=(0, 10))
        
        # 刷新按钮
        refresh_btn = ttk.Button(toolbar, text="🔄 刷新", command=self.refresh_images)
        refresh_btn.pack(side=tk.LEFT, padx=(0, 10))
        
        # 打开网页版按钮
        web_btn = ttk.Button(toolbar, text="🌐 网页版", command=self.open_web_version)
        web_btn.pack(side=tk.LEFT, padx=(0, 10))
        
        # 搜索框
        search_frame = ttk.Frame(toolbar)
        search_frame.pack(side=tk.RIGHT, padx=(10, 0))
        
        ttk.Label(search_frame, text="搜索:").pack(side=tk.LEFT, padx=(0, 5))
        self.search_var = tk.StringVar()
        self.search_var.trace("w", self.filter_images)
        search_entry = ttk.Entry(search_frame, textvariable=self.search_var, width=30)
        search_entry.pack(side=tk.LEFT)
        
        # 主内容区域
        content_frame = ttk.Frame(main_frame)
        content_frame.pack(fill=tk.BOTH, expand=True)
        
        # 左侧图片列表
        left_frame = ttk.Frame(content_frame)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        
        # 图片列表标题
        list_title = ttk.Label(left_frame, text="📷 图片列表", font=("Arial", 12, "bold"))
        list_title.pack(pady=(0, 5))
        
        # 创建Treeview用于显示图片列表
        columns = ("name", "size", "date", "dimensions")
        self.tree = ttk.Treeview(left_frame, columns=columns, show="tree headings", selectmode="extended")
        
        # 设置列
        self.tree.heading("#0", text="")
        self.tree.heading("name", text="文件名")
        self.tree.heading("size", text="大小")
        self.tree.heading("date", text="修改时间")
        self.tree.heading("dimensions", text="尺寸")
        
        self.tree.column("#0", width=50)
        self.tree.column("name", width=200)
        self.tree.column("size", width=80)
        self.tree.column("date", width=150)
        self.tree.column("dimensions", width=100)
        
        # 滚动条
        scrollbar = ttk.Scrollbar(left_frame, orient=tk.VERTICAL, command=self.tree.yview)
        self.tree.configure(yscrollcommand=scrollbar.set)
        
        self.tree.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 绑定事件
        self.tree.bind("<<TreeviewSelect>>", self.on_image_select)
        self.tree.bind("<Double-1>", self.on_image_double_click)
        
        # 右侧预览区域
        right_frame = ttk.Frame(content_frame)
        right_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(10, 0))
        
        # 预览标题
        preview_title = ttk.Label(right_frame, text="👁️ 图片预览", font=("Arial", 12, "bold"))
        preview_title.pack(pady=(0, 5))
        
        # 预览画布
        self.preview_frame = ttk.Frame(right_frame, relief=tk.SUNKEN, borderwidth=2)
        self.preview_frame.pack(fill=tk.BOTH, expand=True)
        
        self.preview_label = ttk.Label(self.preview_frame, text="选择图片进行预览", anchor=tk.CENTER)
        self.preview_label.pack(fill=tk.BOTH, expand=True)
        
        # 图片信息区域
        info_frame = ttk.LabelFrame(right_frame, text="📋 图片信息", padding=10)
        info_frame.pack(fill=tk.X, pady=(10, 0))
        
        self.info_text = tk.Text(info_frame, height=8, wrap=tk.WORD)
        self.info_text.pack(fill=tk.BOTH, expand=True)
        
        # 状态栏
        self.status_bar = ttk.Label(main_frame, text="就绪", relief=tk.SUNKEN)
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X, pady=(10, 0))
        
    def upload_images(self):
        """上传图片"""
        filetypes = [
            ("Image files", "*.jpg *.jpeg *.png *.gif *.webp *.bmp"),
            ("All files", "*.*")
        ]
        
        files = filedialog.askopenfilenames(
            title="选择图片文件",
            filetypes=filetypes
        )
        
        if files:
            self.status_bar.config(text=f"正在上传 {len(files)} 个文件...")
            threading.Thread(target=self.process_uploads, args=(files,)).start()
            
    def process_uploads(self, files):
        """处理上传的文件"""
        success_count = 0
        error_count = 0
        
        for file_path in files:
            try:
                filename = os.path.basename(file_path)
                target_path = os.path.join(self.upload_dir, filename)
                
                # 如果文件已存在，添加序号
                counter = 1
                original_target = target_path
                while os.path.exists(target_path):
                    name, ext = os.path.splitext(original_target)
                    target_path = f"{name}_{counter}{ext}"
                    counter += 1
                
                # 复制文件
                shutil.copy2(file_path, target_path)
                
                # 获取图片信息
                try:
                    with Image.open(target_path) as img:
                        width, height = img.size
                        file_size = os.path.getsize(target_path)
                        
                        self.images_data[filename] = {
                            "path": target_path,
                            "size": file_size,
                            "width": width,
                            "height": height,
                            "date": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                        }
                except Exception as e:
                    print(f"无法读取图片信息: {e}")
                
                success_count += 1
                
            except Exception as e:
                print(f"上传失败 {file_path}: {e}")
                error_count += 1
        
        # 更新UI
        self.root.after(0, self.upload_complete, success_count, error_count)
        
    def upload_complete(self, success_count, error_count):
        """上传完成"""
        self.load_images()
        if error_count == 0:
            messagebox.showinfo("成功", f"成功上传 {success_count} 个文件！")
            self.status_bar.config(text=f"上传完成：{success_count} 个文件")
        else:
            messagebox.showwarning("完成", f"上传完成：{success_count} 个成功，{error_count} 个失败")
            self.status_bar.config(text=f"上传完成：{success_count} 成功，{error_count} 失败")
            
    def load_images(self):
        """加载图片列表"""
        # 清空现有列表
        for item in self.tree.get_children():
            self.tree.delete(item)
        
        # 加载图片数据
        self.images_data.clear()
        
        for filename in os.listdir(self.upload_dir):
            if filename.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.webp', '.bmp')):
                file_path = os.path.join(self.upload_dir, filename)
                try:
                    file_size = os.path.getsize(file_path)
                    file_date = datetime.fromtimestamp(os.path.getmtime(file_path)).strftime("%Y-%m-%d %H:%M:%S")
                    
                    # 获取图片尺寸
                    try:
                        with Image.open(file_path) as img:
                            width, height = img.size
                            dimensions = f"{width}x{height}"
                    except:
                        dimensions = "未知"
                    
                    self.images_data[filename] = {
                        "path": file_path,
                        "size": file_size,
                        "date": file_date,
                        "dimensions": dimensions
                    }
                    
                    # 添加到树形视图
                    size_str = self.format_file_size(file_size)
                    self.tree.insert("", "end", text="", values=(filename, size_str, file_date, dimensions))
                    
                except Exception as e:
                    print(f"加载图片失败 {filename}: {e}")
        
        self.status_bar.config(text=f"共 {len(self.images_data)} 张图片")
        
    def format_file_size(self, size):
        """格式化文件大小"""
        for unit in ['B', 'KB', 'MB', 'GB']:
            if size < 1024.0:
                return f"{size:.1f} {unit}"
            size /= 1024.0
        return f"{size:.1f} TB"
        
    def filter_images(self, *args):
        """过滤图片"""
        search_term = self.search_var.get().lower()
        
        # 清空列表
        for item in self.tree.get_children():
            self.tree.delete(item)
        
        # 重新添加过滤后的图片
        for filename, data in self.images_data.items():
            if search_term in filename.lower():
                size_str = self.format_file_size(data["size"])
                self.tree.insert("", "end", text="", values=(
                    filename, size_str, data["date"], data["dimensions"]
                ))
        
    def on_image_select(self, event):
        """选择图片时"""
        selection = self.tree.selection()
        if selection:
            item = self.tree.item(selection[0])
            filename = item["values"][0]
            self.show_image_preview(filename)
            
    def on_image_double_click(self, event):
        """双击图片时"""
        selection = self.tree.selection()
        if selection:
            item = self.tree.item(selection[0])
            filename = item["values"][0]
            self.open_image_in_viewer(filename)
            
    def show_image_preview(self, filename):
        """显示图片预览"""
        if filename not in self.images_data:
            return
            
        file_path = self.images_data[filename]["path"]
        
        try:
            # 加载并调整图片大小
            with Image.open(file_path) as img:
                # 获取预览区域大小
                frame_width = self.preview_frame.winfo_width()
                frame_height = self.preview_frame.winfo_height()
                
                if frame_width <= 1 or frame_height <= 1:
                    frame_width = 400
                    frame_height = 300
                
                # 调整图片大小以适应预览区域
                img.thumbnail((frame_width - 20, frame_height - 20), Image.Resampling.LANCZOS)
                
                # 转换为PhotoImage
                photo = ImageTk.PhotoImage(img)
                
                # 更新预览标签
                self.preview_label.config(image=photo, text="")
                self.preview_label.image = photo  # 保持引用
                
                # 更新图片信息
                self.update_image_info(filename)
                
        except Exception as e:
            self.preview_label.config(image="", text=f"无法预览图片: {e}")
            
    def update_image_info(self, filename):
        """更新图片信息"""
        if filename not in self.images_data:
            return
            
        data = self.images_data[filename]
        
        info_text = f"""
文件名: {filename}
文件大小: {self.format_file_size(data['size'])}
修改时间: {data['date']}
图片尺寸: {data['dimensions']}
文件路径: {data['path']}
        """.strip()
        
        self.info_text.delete(1.0, tk.END)
        self.info_text.insert(1.0, info_text)
        
    def open_image_in_viewer(self, filename):
        """在系统默认查看器中打开图片"""
        if filename not in self.images_data:
            return
            
        file_path = self.images_data[filename]["path"]
        
        try:
            if os.name == 'nt':  # Windows
                os.startfile(file_path)
            else:  # macOS and Linux
                webbrowser.open(f"file://{file_path}")
        except Exception as e:
            messagebox.showerror("错误", f"无法打开图片: {e}")
            
    def delete_selected(self):
        """删除选中的图片"""
        selection = self.tree.selection()
        if not selection:
            messagebox.showwarning("提示", "请先选择要删除的图片")
            return
            
        filenames = [self.tree.item(item)["values"][0] for item in selection]
        
        if messagebox.askyesno("确认", f"确定要删除选中的 {len(filenames)} 张图片吗？"):
            deleted_count = 0
            for filename in filenames:
                if filename in self.images_data:
                    try:
                        os.remove(self.images_data[filename]["path"])
                        deleted_count += 1
                    except Exception as e:
                        print(f"删除失败 {filename}: {e}")
            
            if deleted_count > 0:
                self.load_images()
                messagebox.showinfo("成功", f"已删除 {deleted_count} 张图片")
                
    def refresh_images(self):
        """刷新图片列表"""
        self.load_images()
        messagebox.showinfo("提示", "图片列表已刷新")
        
    def open_web_version(self):
        """打开网页版本"""
        webbrowser.open("http://localhost:8080")
        messagebox.showinfo("提示", "正在打开网页版本...")

def main():
    """主函数"""
    root = tk.Tk()
    app = MagazineApp(root)
    root.mainloop()

if __name__ == "__main__":
    main()